package com.webank.maling.documentation.repository.graph;

import com.webank.maling.base.model.MethodInfo;
import com.webank.maling.documentation.dto.DocumentationGenerationDto;
import com.webank.maling.documentation.repository.graph.support.GraphSupport;
import com.webank.maling.repository.nebula.NebulaGraphClient;
import com.vesoft.nebula.client.graph.data.ResultSet;
import com.vesoft.nebula.client.graph.data.ValueWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 入口点服务
 * 负责查询和管理代码图谱中的入口节点
 *
 * @author diodehe
 */
@Slf4j
@Service
public class EntryPointRepository {

    private final NebulaGraphClient nebulaGraphClient;

    @Autowired
    public EntryPointRepository(NebulaGraphClient nebulaGraphClient) {
        this.nebulaGraphClient = nebulaGraphClient;
    }

    /**
     * 获取所有入口点
     *
     * @return 入口点列表
     */
    public List<MethodInfo> getAllEntryPoints(DocumentationGenerationDto dto) {
        try {
            log.info("开始查询所有入口点");

            // 查询所有is_entry_point=TRUE的function节点
            String query = """
                    MATCH (v:function{is_entry_point:TRUE})
                    where v.function.repo_id == "%s" and v.function.branch_name == "%s"
                    and (v.function.full_name starts with "com.macro.mall.portal.controller.OmsPortalOrderController"
                    or v.function.full_name starts with "com.macro.mall.controller.OmsOrderReturnApplyController")
                    RETURN v
                    """.formatted(dto.getProjectId(), dto.getBranchName());

            ResultSet resultSet = nebulaGraphClient.execute(query);

            if (!resultSet.isSucceeded()) {
                log.error("查询入口点失败: {}", resultSet.getErrorMessage());
                return List.of();
            }

            List<MethodInfo> entryPoints = new ArrayList<>();

            // 解析查询结果
            for (int i = 0; i < resultSet.rowsSize(); i++) {
                try {
                    ValueWrapper nodeWrapper = resultSet.rowValues(i).get(0);
                    if (nodeWrapper.isVertex()) {
                        MethodInfo methodInfo = GraphSupport.parseVertexToMethodInfo(nodeWrapper.asNode());
                        if (methodInfo != null) {
                            entryPoints.add(methodInfo);
                        }
                    }
                } catch (Exception e) {
                    log.warn("解析入口点数据时发生错误，跳过该记录", e);
                }
            }

            log.info("成功查询到 {} 个入口点", entryPoints.size());
            return entryPoints;

        } catch (Exception e) {
            log.error("查询所有入口点时发生错误", e);
            return List.of();
        }
    }

    /**
     * 根据ID获取入口点信息
     *
     * @param entryPointId 入口点ID
     * @return 入口点信息，如果不存在返回null
     */
    public MethodInfo getEntryPointById(String entryPointId) {
        try {
            log.debug("查询入口点: {}", entryPointId);

            String query =
                    """
                            MATCH (v:function{is_entry_point:TRUE}) WHERE id(v) == "%s" RETURN v
                            """.formatted(entryPointId);

            ResultSet resultSet = nebulaGraphClient.execute(query);

            if (!resultSet.isSucceeded()) {
                log.error("查询入口点 {} 失败: {}", entryPointId, resultSet.getErrorMessage());
                return null;
            }

            if (resultSet.rowsSize() == 0) {
                log.warn("未找到入口点: {}", entryPointId);
                return null;
            }

            // 解析第一条结果
            ValueWrapper nodeWrapper = resultSet.rowValues(0).get(0);
            if (nodeWrapper.isVertex()) {
                MethodInfo methodInfo = GraphSupport.parseVertexToMethodInfo(nodeWrapper.asNode());
                log.debug("成功获取入口点信息: {}", methodInfo != null ? methodInfo.getMethodName() : "null");
                return methodInfo;
            }

            return null;

        } catch (Exception e) {
            log.error("根据ID查询入口点时发生错误: {}", entryPointId, e);
            return null;
        }
    }

    /**
     * 获取入口点总数
     *
     * @return 入口点总数
     */
    public int getTotalEntryPointsCount() {
        try {
            String query = "MATCH (v:function{is_entry_point:TRUE}) RETURN count(v) as count";

            ResultSet resultSet = nebulaGraphClient.execute(query);

            if (!resultSet.isSucceeded()) {
                log.error("查询入口点总数失败: {}", resultSet.getErrorMessage());
                return 0;
            }

            if (resultSet.rowsSize() > 0) {
                ValueWrapper countWrapper = resultSet.rowValues(0).get(0);
                if (countWrapper.isLong()) {
                    int count = (int) countWrapper.asLong();
                    log.debug("入口点总数: {}", count);
                    return count;
                }
            }

            return 0;

        } catch (Exception e) {
            log.error("获取入口点总数时发生错误", e);
            return 0;
        }
    }

    /**
     * 检查指定方法是否为入口点
     *
     * @param methodId 方法ID
     * @return 是否为入口点
     */
    public boolean isEntryPoint(String methodId) {
        try {
            String query =
                    """
                    MATCH (v:function{is_entry_point:TRUE}) WHERE id(v) == "%s" RETURN count(v) as count",
                    """.formatted(methodId);

            ResultSet resultSet = nebulaGraphClient.execute(query);

            if (!resultSet.isSucceeded()) {
                log.error("检查入口点状态失败: {}", resultSet.getErrorMessage());
                return false;
            }

            if (resultSet.rowsSize() > 0) {
                ValueWrapper countWrapper = resultSet.rowValues(0).get(0);
                if (countWrapper.isLong()) {
                    return countWrapper.asLong() > 0;
                }
            }

            return false;

        } catch (Exception e) {
            log.error("检查方法 {} 是否为入口点时发生错误", methodId, e);
            return false;
        }
    }
}
